package com.supreme.cacheserver.service;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class BloomFilterService {

    private BloomFilter<CharSequence> bloomFilterBuffer = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 100000000, 0.0001);

    private RBloomFilter<Object> redisBloomFilter;

    private Map<String, RBloomFilter<Object>> redisBloomFilterMap = new ConcurrentHashMap<>();

    @Resource
    private RedissonClient redissonClient;

    @PostConstruct
    private void init() {
        redisBloomFilter = redissonClient.getBloomFilter("test-bloom-filter");
        redisBloomFilter.tryInit(10000, 0.05);
    }

    public boolean putItemToBloomFilter(String itemKey) {
        return bloomFilterBuffer.put(itemKey);
    }

    public boolean checkItemInBloomFilter(String itemKey) {
        return bloomFilterBuffer.mightContain(itemKey);
    }

    public void debugRedisBloomFilter() {
        Set<String> set = new HashSet<>(1000);
        List<String> list = new ArrayList<>(1000);
        //向布隆过滤器中填充数据，为了测试真实，我们记录了 1000 个 uuid，另外 9000个作为干扰数据
        for (int i = 0; i < 10000; i++) {
            String uuid = UUID.randomUUID().toString();
            if (i < 1000) {
                set.add(uuid);
                list.add(uuid);
            }

            redisBloomFilter.add(uuid);
        }

        int wrong = 0;  // 布隆过滤器误判的次数
        int right = 0;  // 布隆过滤器正确次数
        for (int i = 0; i < 10000; i++) {
            String str = i % 10 == 0 ? list.get(i / 10) : UUID.randomUUID().toString();
            if (redisBloomFilter.contains(str)) {
                if (set.contains(str)) {
                    right++;
                } else {
                    wrong++;
                }
            }
        }

        //right 为1000
        System.out.println("right:" + right);
        //因为误差率为3%，所以一万条数据wrong的值在30左右
        System.out.println("wrong:" + wrong);
        //过滤器剩余空间大小
        System.out.println(redisBloomFilter.count());
    }

    public void createRedisBloomFilter(String key, long capacity, double errorRate) {
        if (!redisBloomFilterMap.containsKey(key)) {
            RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(key);
            bloomFilter.tryInit(capacity, errorRate);
            redisBloomFilterMap.put(key, bloomFilter);
        }
    }

    public boolean putRedisBloomFilter(String key, String value) {
        RBloomFilter<Object> bloomFilter = redisBloomFilterMap.get(key);
        return Objects.nonNull(bloomFilter) ? bloomFilter.add(value) : Boolean.FALSE;
    }

    public boolean checkRedisBloomFilter(String key, String value) {
        RBloomFilter<Object> bloomFilter = redisBloomFilterMap.get(key);
        return Objects.nonNull(bloomFilter) ? bloomFilter.contains(value) : Boolean.FALSE;
    }
}
